#define IR (default_cpu.ir)
#define PC (default_cpu.pc)
#define OPCODE ((IR & 0x7FU)) // CHECKED
#define RS1    (ZEXT(IR & 0xF8000U) >> 15) // CHECKED
#define RS2    (ZEXT(IR & 0x1F00000U) >> 20) // CHECKED
#define SHAMT RS2
#define RD     (ZEXT(IR & 0xF80U) >> 7) // CHECKED
#define FUNCT7 (ZEXT(IR & 0xFE000000U) >> 25) // CHECKED
#define FUNCT5 RS2 // for rv32f/d
#define FUNCT3 (ZEXT(IR & 0x7000U) >> 12) // CHECKED
#define IMM_I  (SEXT(IR & 0xFFF00000U) >> 20) //CHECKED
#define IMM_S  (SEXT((IR & 0xFE000000U)|((IR&0xF80U)<<13))>>20) // CHECKED
#define IMM_B  (SEXT((ZEXT(IR & 0x7E000000U)>>1)|((IR & 0x80U)<<23)|((IR & 0xF00U)<<12)|(IR & 0x80000000U)) >> 19) // CHECKED
#define IMM_U  (IR & 0xFFFFF000U) // CHECKED
#define IMM_J  ((ZEXT(IR & 0x7FE00000U) >> 20)|(ZEXT(IR&0x100000U)>>9)|(IR&0xFF000U)|(SEXT(IR&0x80000000U)>>11)) // CHECKED
#define RS3    (ZEXT(IR & 0xE0000000U) >> 27)
#define R4_FMT (ZEXT(IR & 0x6000000U) >> 25)
#define R4_RM  (ZEXT(IR & 0x7000U) >> 12)

// 22
#define DEF_R_INST(name,funct7,funct3,opcode,op){   \
    if (OPCODE == (opcode) && FUNCT3 == (funct3) && FUNCT7 == (funct7)) { \
        printf ("%s x%d,x%d,x%d\n", #name, RD, RS1, RS2); \
        {op}\
        goto executed;\
    }\
}
#define DEF_I_INST(name,funct3,opcode,op){  \
    if (OPCODE == (opcode) && FUNCT3 == (funct3) ) {\
        printf ("%s x%d,%d(x%d)\n", #name, RD, IMM_I, RS1);\
        {op}\
        goto executed;\
    }\
}
#define DEF_S_INST(name,funct3,opcode,op){\
    if (OPCODE == (opcode) && FUNCT3 == (funct3)) {\
        printf ("%s x%d,%d(x%d)\n", #name, RS2, IMM_S, RS1);\
        {op}\
        goto executed;\
    }\
}
#define DEF_B_INST(name,funct3,opcode,op){\
    if (OPCODE == (opcode) && FUNCT3 == (funct3)) {\
        printf ("%s x%d,x%d,%d\n", #name, RS1, RS2, IMM_B);\
        {op}\
        goto executed;\
    }\
}
#define DEF_U_INST(name,opcode,op){\
    if (OPCODE == (opcode)) {\
        printf ("%s x%d,%d\n", #name, RD, ZEXT IMM_U >> 12);\
        {op}\
        goto executed;\
    }\
}
#define DEF_J_INST(name,opcode,op){\
    if (OPCODE == (opcode)) {\
        printf ("%s x%d,%d | IR:%d\n", #name, RD, IMM_J,IR);\
        goto executed;\
        {op}\
    }\
}

#define DEF_I_SP_INST(name,funct7,funct3,opcode,op) {\
    if (OPCODE == (opcode) && FUNCT3 == (funct3) && FUNCT7 == (funct7)) { \
        printf ("%s x%d,x%d,%d\n", #name, RD, RS1, RS2); \
        {op}\
        goto executed;\
    }\
}\

#define DEF_I_JMP_INST(name,funct3,opcode,op) { \
    if (OPCODE == (opcode) && FUNCT3 == (funct3) ) {\
        printf ("%s x%d,%d(x%d)\n", #name, RD, IMM_I, RS1);\
        {op}\
        goto executed;\
    }\
}

#define DEF_R4_INST(name, fmt, opcode, op) { \
    if (OPCODE == (opcode) && R4_FMT == (fmt)) { \
        printf ("%s f%d,f%d,f%d,f%d\n", #name, RD, RS1, RS2, RS3);\
        {op}\
        goto executed;\
    } \
}

#define DEF_R_SP_INST(name,funct7,opcode,op){   \
    if (OPCODE == (opcode) && FUNCT7 == (funct7)) { \
        printf ("%s f%d,f%d,f%d\n", #name, RD, RS1, RS2); \
        {op}\
        goto executed;\
    }\
}

#define DEF_R2_INST(name,funct7, funct5 ,opcode,op){   \
    if (OPCODE == (opcode) && FUNCT7 == (funct7) && FUNCT5 == (funct5)) { \
        printf ("%s d%d,s%d\n", #name, RD, RS1); \
        {op}\
        goto executed;\
    }\
}

#define DEF_UNIQUE_INST(name, match, op) {\
    if (IR == (match)) { \
        {op}\
        goto executed;\
    }\
}
